using NuGet.Packaging;

using OpenIddict.Abstractions;

using static OpenIddict.Abstractions.OpenIddictConstants;


namespace Liuliu.Fsb.Services.Identity.Api
{
    public class Worker(IServiceProvider rootProvider) : IHostedService
    {
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            using var scope = rootProvider.CreateScope();
            var provider = scope.ServiceProvider;

            await CreateApplications(provider);

            await CreateScopes(provider);
        }

        private async Task CreateApplications(IServiceProvider provider)
        {
            var manager = provider.GetRequiredService<IOpenIddictApplicationManager>();

            var clientId = "VueApp.Client";
            if (await manager.FindByClientIdAsync(clientId) == null)
            {
                await manager.CreateAsync(new OpenIddictApplicationDescriptor
                {
                    ClientId = clientId,
                    DisplayName = "Vue前端",
                    ClientType = ClientTypes.Public,
                    Permissions =
                    {
                        Permissions.Endpoints.Token,
                        Permissions.Endpoints.Authorization,
                        Permissions.Endpoints.EndSession,
                        Permissions.GrantTypes.AuthorizationCode,
                        Permissions.GrantTypes.RefreshToken,
                        Permissions.ResponseTypes.Code,
                        Permissions.Scopes.Email,
                        Permissions.Scopes.Profile,
                        Permissions.Scopes.Roles,
                        Permissions.Prefixes.Scope + "identity_api",
                        Permissions.Prefixes.Scope + "softwares_api",
                        Permissions.Prefixes.Scope + "games_api"
                    },
                    Requirements =
                    {
                        Requirements.Features.ProofKeyForCodeExchange
                    },
                    RedirectUris = { new Uri("http://localhost:5666/signin-oidc") },
                    PostLogoutRedirectUris = { new Uri("http://localhost:5666/signout-oidc") }
                });
            }

            clientId = "Apifox";
            if (await manager.FindByClientIdAsync(clientId) == null)
            {
                await manager.CreateAsync(new OpenIddictApplicationDescriptor()
                {
                    ClientId = clientId,
                    ClientSecret = "984CAC06-C327-42E7-B68B-F8D2F908A4DC",
                    DisplayName = "Apifox",
                    Permissions =
                    {
                        Permissions.Endpoints.Token,
                        Permissions.Endpoints.Authorization,
                        Permissions.Endpoints.EndSession,
                        Permissions.GrantTypes.AuthorizationCode,
                        Permissions.GrantTypes.RefreshToken,
                        Permissions.ResponseTypes.Code,
                        Permissions.Scopes.Email,
                        Permissions.Scopes.Profile,
                        Permissions.Scopes.Roles,
                        Permissions.Prefixes.Scope + "identity_api",
                        Permissions.Prefixes.Scope + "softwares_api",
                        Permissions.Prefixes.Scope + "games_api"
                    },
                    RedirectUris = { new Uri("http://localhost:8080/callback") },
                });
            }

            var clients = new[]
            {
                new { ClientId = "Identity.Service", ClientSecret = "B4939BE1-17FF-49E0-9D01-03A13EDEA3BA", DisplayName = "认证服务" },
                new { ClientId = "Softwares.Service", ClientSecret = "A925A962-521F-4A8F-A22D-672D96FB9E07", DisplayName = "软件服务" },
                new { ClientId = "Games.Service", ClientSecret = "FD688983-E338-4DE2-B8DE-114F753A192E", DisplayName = "游戏服务" },
            };

            foreach (var client in clients)
            {
                if (await manager.FindByClientIdAsync(client.ClientId) == null)
                {
                    await manager.CreateAsync(new OpenIddictApplicationDescriptor()
                    {
                        ClientId = client.ClientId,
                        ClientSecret = client.ClientSecret,
                        DisplayName = client.DisplayName,
                        Permissions =
                        {
                            Permissions.Endpoints.Introspection
                        }
                    });
                }
            }
        }

        private async Task CreateScopes(IServiceProvider provider)
        {
            var manager = provider.GetRequiredService<IOpenIddictScopeManager>();

            var scopes = new[]
            {
                new { Name = "identity_api", DisplayName = "认证服务API", Resource = new[] { "Identity.Service" } },
                new { Name = "softwares_api", DisplayName = "软件服务API", Resource = new[] { "Softwares.Service" } },
                new { Name = "games_api", DisplayName = "游戏服务API", Resource = new[] { "Games.Service" } },
            };

            foreach (var scope in scopes)
            {
                if (await manager.FindByNameAsync(scope.Name) == null)
                {
                    var desc = new OpenIddictScopeDescriptor()
                    {
                        Name = scope.Name,
                        DisplayName = scope.DisplayName
                    };
                    desc.Resources.AddRange(scope.Resource);
                    await manager.CreateAsync(desc);
                }
            }
        }

        public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
    }
}
